package com.chatdating.websocket;

import com.chatdating.entity.User;
import com.chatdating.entity.dto.MessageSendDto;
import com.chatdating.entity.vo.LoginInVo;
import com.chatdating.mapper.UserMapper;
import com.chatdating.redis.RedisComponet;
import com.chatdating.utils.EmptyUtil;
import com.chatdating.utils.JsonUtils;
import com.qcloud.cos.model.ciModel.auditing.UserInfo;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;



@Component("channelContextUtils")
public class ChannelContextUtils {

    private static final Logger logger = LoggerFactory.getLogger(ChannelContextUtils.class);

    @Resource
    private RedisComponet redisComponet;


    @Autowired
    private UserMapper userMapper ;

    public static final ConcurrentMap<String, Channel> USER_CONTEXT_MAP = new ConcurrentHashMap();  //用户与channel的绑定  （不能放在redis中 因为chanell不能进行序列化 ）

    /**
     * 加入通道 将channel 与userId 绑定
     *
     * @param usesrname
     * @param channel
     */
    public void addContext(String usesrname, Channel channel) {
        try {
            String channelId = channel.id().toString();  //获取channel的唯一标识 channelId
            AttributeKey attributeKey = null;            // 获取到channel的属性key
            if (!AttributeKey.exists(channelId)) {       // 如果属性key不存在，创建一个
                attributeKey = AttributeKey.newInstance(channel.id().toString());
            } else {                                     // 如果属性key存在，获取到
                attributeKey = AttributeKey.valueOf(channel.id().toString());
            }
            channel.attr(attributeKey).set(usesrname);     // 将channel与userId绑定

           //获取到登录人的所有联系人id  （在用户登陆时 将联系人是好友的id存放在redis中）
             List<LoginInVo> contactList = redisComponet.getUserContactList(usesrname);

            USER_CONTEXT_MAP.put(usesrname, channel);        // 将channel与userId绑定到map中


           // redisComponet.saveUserHeartBeat(userId);      // 连接之后保存用户心跳时间

            //更新用户最后连接时间
            userMapper.updateLoginTimeByUsername(String.valueOf(System.currentTimeMillis()), usesrname);

            //给用户发送消息
            //获取用户最后离线时间
            User user = userMapper.findByName(usesrname);
            Long lastTime = user.getLastTime();
            if(EmptyUtil.isEmpty(lastTime)){
                lastTime = Long.valueOf(0);
            }
            User byName = userMapper.findByName(usesrname);
            String id = String.valueOf(byName.getId());

            //这里避免毫秒时间差，所以减去1秒的时间
            //如果时间太久，只取最近三天的消息数
           /* Long lastOffTime = sourceLastOffTime;   //最后一次登录的时间
            if (sourceLastOffTime != null && System.currentTimeMillis() - Constants.MILLISECOND_3DAYS_AGO > sourceLastOffTime) {
                // 如果大于三天，只取最近三天的消息数
                lastOffTime = System.currentTimeMillis() - Constants.MILLISECOND_3DAYS_AGO;
            }*/
            /*
            *//**
             * 2、查询未读聊天消息
             */

            Map<String, Integer> stringIntegerMap = userMapper.countUnreadMessagesBySession(lastTime, id);
            /*//查询用户的联系人
            UserContactQuery contactQuery = new UserContactQuery();
            contactQuery.setContactType(UserContactTypeEnum.GROUP.getType());
            contactQuery.setUserId(userId);
            List<UserContact> groupContactList = userContactMapper.selectList(contactQuery);   //查询出自己的所有群组集合
            List<String> groupIdList = groupContactList.stream().map(item -> item.getContactId()).collect(Collectors.toList());
            //将自己也加进去
            groupIdList.add(userId);   //凑成了 联系人是  自己 和  群组里有自己 的id集合*/
          /*  ChatMessageQuery messageQuery = new ChatMessageQuery();
            messageQuery.setContactIdList(groupIdList);
            messageQuery.setLastReceiveTime(lastOffTime);
            List<ChatMessage> chatMessageList = chatMessageMapper.selectList(messageQuery); //查询出所有的离线消息
            wsInitData.setChatMessageList(chatMessageList);
*/

            /*
             * 3、查询好友申请
             *//*
            UserContactApplyQuery applyQuery = new UserContactApplyQuery();
            applyQuery.setReceiveUserId(userId);
            applyQuery.setLastApplyTimestamp(sourceLastOffTime);
            applyQuery.setStatus(UserContactApplyStatusEnum.INIT.getStatus());
            Integer applyCount = userContactApplyMapper.selectCount(applyQuery);
            wsInitData.setApplyCount(applyCount);
*/
            //登录之后向客户端发送消息
            MessageSendDto messageSendDto = new MessageSendDto();
            messageSendDto.setContacts(contactList);
            messageSendDto.setMapNoRead(stringIntegerMap);
            //初始化消息
            messageSendDto.setContactId(usesrname);
            sendMsg(messageSendDto, usesrname);
        } catch (Exception e) {
            logger.error("初始化链接失败", e);
        }
    }
    /**
     * 删除通道连接异常
     *
     * @param channel
     */
    public void removeContext(Channel channel) {
        Attribute<String> attribute = channel.attr(AttributeKey.valueOf(channel.id().toString()));
        String username = attribute.get();        //获取用户id
        if (EmptyUtil.isNotEmpty(username)) {
            USER_CONTEXT_MAP.remove(username);    //从map之中删除
        }
        redisComponet.removeUserHeartBeat(username);
        userMapper.updateLastTime(String.valueOf(System.currentTimeMillis()), username);
    }

   /* public void closeContext(String userId) {
        if (EmptyUtil.isEmpty(userId)) {
            return;
        }
        redisComponet.cleanUserTokenByUserId(userId);
        Channel channel = USER_CONTEXT_MAP.get(userId);
        USER_CONTEXT_MAP.remove(userId);
        if (channel != null) {
            channel.close();
        }
    }*/
    /**
     * 发送消息给用户
     */
    private void send2User(MessageSendDto messageSendDto) {
        String contactId = messageSendDto.getContactId();
        sendMsg(messageSendDto, contactId);
       /* //强制下线
        if (MessageTypeEnum.FORCE_OFF_LINE.getType().equals(messageSendDto.getMessageType())) {
            closeContext(contactId);
        }*/
    }
    /**
     * 发送消息
     *
     * @param messageSendDto
     * @param recivename
     */
    public static void sendMsg(MessageSendDto messageSendDto, String recivename) {
        if (recivename == null) {
            return;
        }
        Channel sendChannel = USER_CONTEXT_MAP.get(recivename);
        if (sendChannel == null) {
            return;
        }
        //相当于客户而言，联系人就是发送人，所以这里转换一下再发送,好友打招呼信息发送给自己需要特殊处理
     /*   if (MessageTypeEnum.ADD_FRIEND_SELF.getType().equals(messageSendDto.getMessageType())) {
            UserInfo userInfo = (UserInfo) messageSendDto.getExtendData();
            messageSendDto.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
            messageSendDto.setContactId(userInfo.getUserId());
            messageSendDto.setContactName(userInfo.getNickName());
            messageSendDto.setExtendData(null);
        } else {*/
            messageSendDto.setContactId(messageSendDto.getSendUserId());
            messageSendDto.setContactName("zhangsanfeng");
       // }
        //发送消息*/
        sendChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.convertObj2Json(messageSendDto)));
    }
}

